{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "source": [
    "python的元类(metaclass)和虚基类（ABC）\n",
    "\n",
    "\n",
    "== metaclass  ==\n",
    "\n",
    "== ABC虚基类 ==\n",
    "\n",
    "<!-- TEASER_END -->\n",
    "\n",
    "\n",
    "[python 元类](https://www.ibm.com/developerworks/cn/linux/l-pymeta/index.html \"python 元类\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "New called with\n",
      "metaname <class '__main__.MyMeta'>\n",
      "classname Kls\n",
      "baseclasses ()\n",
      "attrs {'__module__': '__main__', '__qualname__': 'Kls', '__init__': <function Kls.__init__ at 0x105be4c80>, 'printd': <function Kls.printd at 0x105be4598>}\n",
      "init called with\n",
      "classobject <class '__main__.Kls'>\n",
      "classname Kls\n",
      "baseclasses ()\n",
      "attrs {'__module__': '__main__', '__qualname__': 'Kls', '__init__': <function Kls.__init__ at 0x105be4c80>, 'printd': <function Kls.printd at 0x105be4598>, 'getdata': <function a.getd3 at 0x105be4bf8>}\n",
      "arun\n",
      "arunarunarun\n"
     ]
    }
   ],
   "source": [
    "\n",
    "class a:\n",
    "    def __init__(self, data):\n",
    "        self.data = data\n",
    "        \n",
    "    def getd3(self):\n",
    "        return self.data * 3\n",
    "    \n",
    " \n",
    "class MyMeta(type):\n",
    "    def __new__(metaname, classname, baseclasses, attrs):\n",
    "        print('New called with')\n",
    "        print('metaname', metaname)\n",
    "        print('classname', classname)\n",
    "        print('baseclasses', baseclasses)\n",
    "        print('attrs', attrs)\n",
    "        attrs['getdata'] = a.__dict__['getd3']\n",
    "        # attrs['getdata'] = a.getd3\n",
    "        return type.__new__(metaname, classname, baseclasses, attrs)\n",
    "    \n",
    "    def __init__(classobject, classname, baseclasses, attrs):\n",
    "        print('init called with')\n",
    "        print('classobject', classobject)\n",
    "        print('classname', classname)\n",
    "        print('baseclasses', baseclasses)\n",
    "        print('attrs', attrs)\n",
    "\n",
    "# py2 和py3对metaclass工作方式不也一样，一下是py3写法\n",
    "class Kls(metaclass=MyMeta):\n",
    "    def __init__(self,data):\n",
    "        self.data = data\n",
    "\n",
    "    def printd(self):\n",
    "        print(self.data)\n",
    "        \n",
    "ik = Kls('arun')\n",
    "ik.printd()\n",
    "print(ik.getdata())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": [
    "from abc import ABCMeta\n",
    "\n",
    "\n",
    "# 构造元类\n",
    "def with_metaclass(meta, *bases):\n",
    "    # This requires a bit of explanation: the basic idea is to make a\n",
    "    # dummy metaclass for one level of class instantiation that replaces\n",
    "    # itself with the actual metaclass.  Because of internal type checks\n",
    "    # we also need to make sure that we downgrade the custom metaclass\n",
    "    # for one level to something closer to type (that's why __call__ and\n",
    "    # __init__ comes back from type etc.).\n",
    "    #\n",
    "    # This has the advantage over six.with_metaclass in that it does not\n",
    "    # introduce dummy classes into the final MRO.\n",
    "    class metaclass(meta):\n",
    "        __call__ = type.__call__\n",
    "        __init__ = type.__init__\n",
    "        def __new__(cls, name, this_bases, d):\n",
    "            if this_bases is None:\n",
    "                return type.__new__(cls, name, (), d)\n",
    "            return meta(name, bases, d)\n",
    "\n",
    "    return metaclass('temporary_class', None, {})\n",
    "\n",
    "\n",
    "class MyList(with_metaclass(ABCMeta,  )):\n",
    "    pass\n",
    "\n",
    "\n",
    "MyList.register(list)\n",
    "\n",
    "assert issubclass(list, MyList)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'int'>\n"
     ]
    }
   ],
   "source": [
    "from abc import ABC\n",
    "import collections\n",
    "\n",
    "print(type(1))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'collections.abc.Set'>\n",
      "<class 'type'>\n",
      "<class 'set'>\n",
      "set() -> new empty set object\n",
      "set(iterable) -> new set object\n",
      "\n",
      "Build an unordered collection of unique elements.\n"
     ]
    }
   ],
   "source": [
    "\n",
    "print(collections.Set)\n",
    "\n",
    "print(set.__class__)\n",
    "\n",
    "print(set)\n",
    "\n",
    "print(set.__doc__)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "name": "python-meta-class.ipynb",
  "nikola": {
   "category": "",
   "date": "2019-04-15 18:10:46 UTC+08:00",
   "description": "",
   "link": "",
   "slug": "python-meta-class",
   "tags": "",
   "title": "python meta class",
   "type": "text"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
